<?php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;

class MakePackage extends Command
{
    protected $signature = 'make:package {vendor} {name} {--view} {--assets}';
    protected $description = 'Scaffold a local package under packages/{vendor}/{name}';
    protected Filesystem $files;

    public function __construct(Filesystem $files)
    {
        parent::__construct();
        $this->files = $files;
    }

    public function handle(): int
    {
        $vendor = Str::studly($this->argument('vendor'));
        $name   = Str::snake($this->argument('name'));
        $psr    = Str::studly($name);

        $base = base_path("packages/{$vendor}/{$name}");
        $src  = "{$base}/src";

        // 目录
        $dirs = [
            $base, $src, "{$src}/views", "{$src}/facades", "{$src}/config",
        ];
        if ($this->option('assets')) {
            $dirs[] = "{$base}/assets/css";
            $dirs[] = "{$base}/assets/js";
            $dirs[] = "{$base}/assets/images";
        }
        foreach ($dirs as $d) {
            $this->files->ensureDirectoryExists($d);
        }

        // composer.json
        $composer = [
            'name'        => strtolower("{$vendor}/{$name}"),
            'description' => "{$psr} package",
            'license'     => 'MIT',
            'autoload'    => [
                'psr-4' => [
                    "{$vendor}\\{$psr}\\" => "src/"
                ]
            ],
            'extra' => [
                'laravel' => [
                    'providers' => ["{$vendor}\\{$psr}\\{$psr}ServiceProvider"]
                ]
            ]
        ];
        $this->files->put("{$base}/composer.json", json_encode($composer, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT));

        // ServiceProvider
        $provider = <<<PHP
        <?php
        namespace {$vendor}\\{$psr};

        use Illuminate\\Support\\ServiceProvider;

        class {$psr}ServiceProvider extends ServiceProvider
        {
            protected \$defer = true;

            public function register(): void
            {
                \$this->app->singleton('{$name}', fn (\$app) => new {$psr}(\$app['session'], \$app['config']));
                // 合并包配置 初始化默认配置
                \$this->mergeConfigFrom(__DIR__.'/config/{$name}.php', '{$name}');
            }

            public function boot(): void
            {
                \$this->loadViewsFrom(__DIR__.'/views', '{$name}');
                \$this->publishes([
                    __DIR__.'/config/{$name}.php' => config_path('{$name}.php'),
                    __DIR__.'/views' => resource_path('resources/views/vendor/{$name}'),
                ], '{$name}');
            }

            public function provides(): array
            {
                // 因为延迟加载 所以要定义 provides 函数 具体参考laravel 文档
                return ['{$name}'];
            }
        }
        PHP;
        $this->files->put("{$src}/{$psr}ServiceProvider.php", trim($provider)."\n");

        // Core class
        $core = <<<PHP
        <?php
        namespace {$vendor}\\{$psr};

        use Illuminate\\Session\\SessionManager;
        use Illuminate\\Config\\Repository;
        use App\\BasePackage;

        class {$psr} extends BasePackage
        {
            protected \$session;
            protected \$config;
            protected \$name = '{$name}';
            protected \$id;

            public function __construct(SessionManager \$session, Repository \$config)
            {
                \$this->session = \$session;
                \$this->config = \$config;
                \$this->id = self::get_id();
            }
        }
        PHP;
        $this->files->put("{$src}/{$psr}.php", trim($core)."\n");

        // Facade
        $facade = <<<PHP
        <?php
        namespace {$vendor}\\{$psr}\\Facades;

        use Illuminate\\Support\\Facades\\Facade;

        class {$psr} extends Facade
        {
            protected static function getFacadeAccessor(): string
            {
                return '{$name}';
            }
        }
        PHP;
        $this->files->put("{$src}/facades/{$psr}.php", trim($facade)."\n");

        // config
        $this->files->put("{$src}/config/{$name}.php", "<?php\nreturn [\n    // config here\n];\n");

        // view
        if ($this->option('view')) {
            $this->files->put("{$src}/views/{$name}.blade.php", "@extends('layouts.empty')\n<div>{$name} demo view</div>\n");
        }

        // 应用 composer.json 加上 PSR-4（可选，如果你想立即通过应用自动加载）
        $appComposerPath = base_path('composer.json');
        $appComposer = json_decode(file_get_contents($appComposerPath), true);
        $appComposer['autoload']['psr-4']["{$vendor}\\{$psr}\\"] = "packages/{$vendor}/{$name}/src/";
        file_put_contents($appComposerPath, json_encode($appComposer, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT));

        // 追加 到 config/app.php 中的 providers 和 aliases
        $appConfigPath = base_path('config/app.php');
        $appConfig = include $appConfigPath;
        $appConfig['providers'][] = "{$vendor}\\{$psr}\\{$psr}ServiceProvider";
        $appConfig['aliases']["{$psr}"] = "{$vendor}\\{$psr}\\Facades\\{$psr}";
        file_put_contents($appConfigPath, "<?php\nreturn " . var_export($appConfig, true) . ";\n");

        $this->info("Package scaffolded at packages/{$vendor}/{$name}");
        $this->warn("Run: composer dump-autoload -o");
        return Command::SUCCESS;
    }
}